import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'

const AES_KEY = '__aes__'

export const getAESkey = (num: 16 | 32 = 16) => {
  let aesKey = sessionStorage.getItem(AES_KEY)
  if (!aesKey) {
    aesKey = makeRandom(num)
    sessionStorage.setItem(AES_KEY, aesKey)
  }
  return aesKey
}

/**
 * aes 解密
 */
export function AESDecrypt(str: string) {
  const key = CryptoJS.enc.Utf8.parse(getAESkey())
  const decrypt = CryptoJS.AES.decrypt(str, key, {
    iv: key,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
  })
  return CryptoJS.enc.Utf8.stringify(decrypt).toString()
}

/**
 * aes 加密
 */
export function AESEncrypt(str: string) {
  const key = CryptoJS.enc.Utf8.parse(getAESkey())
  const srcs = CryptoJS.enc.Utf8.parse(str)
  const encrypted = CryptoJS.AES.encrypt(srcs, key, {
    iv: key,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
  })
  return encrypted.toString()
}

/**
 * 通过公钥将对称密钥加密后并返回
 * @param pubKey 非对称加密公钥
 */
export function getEncryptAESKey(pubKey: string) {
  const encrypt = new JSEncrypt()
  encrypt.setPublicKey(pubKey)
  // encrypt.encrypt 内部已经包含一次base64加密
  return encrypt.encrypt(window.btoa(getAESkey()))
}

// 获取随机值
function makeRandom(len: number) {
  const str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
  const strLen = str.length
  let tempStr = ''
  for (let x = 0; x < len; ++x) {
    tempStr += str[Math.floor(Math.random() * strLen)]
  }
  return tempStr
}
